package math.geom3d;

import math.base.Point3d;
import math.base.Vector3d;
import math.geomUtils.SurfaceType;

/**
 * @author Saga
 *
 */
public final class CylindricalSurface3d extends ElementarySurface3d {

    @Override
    public final SurfaceType getSurfaceType() {
        return SurfaceType.CYLINDRICAL_SURFACE;
    }

    @Override
    public final void uReverse() {

    }

    @Override
    public final Surface3d uReversed() {
        return null;
    }

    @Override
    public final void vReverse() {

    }

    @Override
    public final Surface3d vReversed() {
        return null;
    }


    @Override
    public final boolean isUPeriodic() {
        return true;
    }

    @Override
    public final double getUPeriod() {
        return Math.PI * 2.0;
    }

    @Override
    public final boolean isVPeriodic() {
        return false;
    }

    @Override
    public final double getVPeriod() {
        throw new ArithmeticException("");
    }

    @Override
    public final double getUFirstParameter() {
        return 0.0;
    }

    @Override
    public final double getULastParameter() {
        return Math.PI * 2.0;
    }

    @Override
    public final double getVFirstParameter() {
        return Double.NEGATIVE_INFINITY;
    }

    @Override
    public final double getVLastParameter() {
        return Double.POSITIVE_INFINITY;
    }

    @Override
    public final Point3d calcValue(final double _uParam, final double _vParam) {
        final double cosVal = Math.cos(_uParam);
        final double sinVal = Math.sin(_uParam);

        return this.pos.getOrigin().added(this.pos.getDirectX().multiplied(cosVal * this.radius))
                .added(this.pos.getDirectY().multiplied(sinVal * this.radius)).added(
                        this.pos.getDirectZ().multiplied(_vParam));
    }

    @Override
    public final Vector3d calcDerivativeU(final double _uParam, final double _vParam) {
        return null;
    }

    @Override
    public final Vector3d calcDerivativeV(final double _uParam, final double _vParam) {
        return null;
    }

    @Override
    public final void calcDerivative(final double _uParam, final double _vParam,
            final Vector3d _derU,
            final Vector3d _derV) {


    }

    @Override
    public final Vector3d calcDerivativeN(final double _uParam, final double _vParam,
            final int _uOrder,
            final int _vOrder) {
        return null;
    }

    @Override
    public final void calcValueAndDerivative1(final double _uParam, final double _vParam,
            final Point3d _pt, final Vector3d _derU, final Vector3d _derV) {
        final double cosVal = Math.cos(_uParam);
        final double sinVal = Math.sin(_uParam);

        _pt.setCoord(this.pos.getOrigin().getCoord().added(
                this.pos.getDirectX().getCoord().multiplied(cosVal * this.radius))
                .added(this.pos.getDirectY().getCoord().multiplied(sinVal * this.radius))
                .added(this.pos.getDirectZ().getCoord().multiplied(_vParam)));

        _derU.setCoord(this.pos.getDirectX().getCoord().multiplied(-sinVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(cosVal * this.radius)));
        _derV.setCoord(this.pos.getDirectZ().getCoord());
    }

    @Override
    public final void calcValueAndDerivative2(final double _uParam, final double _vParam,
            final Point3d _pt, final Vector3d _der1U, final Vector3d _der1V, final Vector3d _der2U,
            final Vector3d _der2V, final Vector3d _der2UV) {
        final double cosVal = Math.cos(_uParam);
        final double sinVal = Math.sin(_uParam);

        _pt.setCoord(this.pos.getOrigin().getCoord().added(
                this.pos.getDirectX().getCoord().multiplied(cosVal * this.radius))
                .added(this.pos.getDirectY().getCoord().multiplied(sinVal * this.radius))
                .added(this.pos.getDirectZ().getCoord().multiplied(_vParam)));

        _der1U.setCoord(this.pos.getDirectX().getCoord().multiplied(-sinVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(cosVal * this.radius)));
        _der1V.setCoord(this.pos.getDirectZ().getCoord());

        _der2U.setCoord(this.pos.getDirectX().getCoord().multiplied(-cosVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(-sinVal * this.radius)));
        _der2V.init(0.0, 0.0, 0.0);
        _der2UV.init(0.0, 0.0, 0.0);
    }

    @Override
    public final void calcValueAndDerivative3(final double _uParam, final double _vParam,
            final Point3d _pt, final Vector3d _der1U, final Vector3d _der1V, final Vector3d _der2U,
            final Vector3d _der2V, final Vector3d _der2UV, final Vector3d _der3U,
            final Vector3d _der3V, final Vector3d _der3UUV, final Vector3d _der3UVV) {
        final double cosVal = Math.cos(_uParam);
        final double sinVal = Math.sin(_uParam);

        _pt.setCoord(this.pos.getOrigin().getCoord().added(
                this.pos.getDirectX().getCoord().multiplied(cosVal * this.radius))
                .added(this.pos.getDirectY().getCoord().multiplied(sinVal * this.radius))
                .added(this.pos.getDirectZ().getCoord().multiplied(_vParam)));

        _der1U.setCoord(this.pos.getDirectX().getCoord().multiplied(-sinVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(cosVal * this.radius)));
        _der1V.setCoord(this.pos.getDirectZ().getCoord());

        _der2U.setCoord(this.pos.getDirectX().getCoord().multiplied(-cosVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(-sinVal * this.radius)));
        _der2V.init(0.0, 0.0, 0.0);
        _der2UV.init(0.0, 0.0, 0.0);

        _der3U.setCoord(this.pos.getDirectX().getCoord().multiplied(sinVal * this.radius)
                .added(this.pos.getDirectY().getCoord().multiplied(-cosVal * this.radius)));
        _der3V.init(0.0, 0.0, 0.0);
        _der3UUV.init(0.0, 0.0, 0.0);
        _der3UVV.init(0.0, 0.0, 0.0);
    }

    @Override
    public final Curve3d calcUISOCurve(final double _param) {
        return null;
    }

    @Override
    public final Curve3d calcVISOCurve(final double _param) {
        return null;
    }

    @Override
    public final CylindricalSurface3d clone() {
        return null;
    }

    private double radius;
}
